|
|
|
/* 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.library.history
|
|
|
|
|
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import androidx.core.view.isVisible
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
|
|
import androidx.recyclerview.widget.SimpleItemAnimator
|
|
|
|
import mozilla.components.support.base.feature.UserInteractionHandler
|
|
|
|
import org.mozilla.fenix.R
|
|
|
|
import org.mozilla.fenix.databinding.ComponentHistoryBinding
|
|
|
|
import org.mozilla.fenix.ext.components
|
|
|
|
import org.mozilla.fenix.library.LibraryPageView
|
|
|
|
import org.mozilla.fenix.theme.ThemeManager
|
|
|
|
|
|
|
|
/**
|
|
|
|
* View that contains and configures the History List
|
|
|
|
*/
|
|
|
|
class HistoryView(
|
|
|
|
container: ViewGroup,
|
|
|
|
val interactor: HistoryInteractor
|
|
|
|
) : LibraryPageView(container), UserInteractionHandler {
|
|
|
|
|
|
|
|
val binding = ComponentHistoryBinding.inflate(
|
|
|
|
LayoutInflater.from(container.context), container, true
|
|
|
|
)
|
|
|
|
|
|
|
|
var mode: HistoryFragmentState.Mode = HistoryFragmentState.Mode.Normal
|
|
|
|
private set
|
|
|
|
|
|
|
|
val historyAdapter = HistoryAdapter(interactor)
|
|
|
|
private val layoutManager = LinearLayoutManager(container.context)
|
|
|
|
|
|
|
|
init {
|
|
|
|
binding.historyList.apply {
|
|
|
|
layoutManager = this@HistoryView.layoutManager
|
|
|
|
adapter = historyAdapter
|
|
|
|
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
|
|
|
}
|
|
|
|
|
|
|
|
val primaryTextColor =
|
|
|
|
ThemeManager.resolveAttribute(R.attr.textPrimary, context)
|
|
|
|
binding.swipeRefresh.setColorSchemeColors(primaryTextColor)
|
|
|
|
binding.swipeRefresh.setOnRefreshListener {
|
|
|
|
interactor.onRequestSync()
|
|
|
|
binding.historyList.scrollToPosition(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun update(state: HistoryFragmentState) {
|
|
|
|
val oldMode = mode
|
|
|
|
|
|
|
|
binding.progressBar.isVisible = state.isDeletingItems
|
|
|
|
binding.swipeRefresh.isRefreshing = state.mode === HistoryFragmentState.Mode.Syncing
|
|
|
|
binding.swipeRefresh.isEnabled =
|
|
|
|
state.mode === HistoryFragmentState.Mode.Normal || state.mode === HistoryFragmentState.Mode.Syncing
|
|
|
|
mode = state.mode
|
|
|
|
|
|
|
|
historyAdapter.updatePendingDeletionIds(state.pendingDeletionIds)
|
|
|
|
|
|
|
|
updateEmptyState(state.pendingDeletionIds.size != historyAdapter.currentList?.size)
|
|
|
|
|
|
|
|
historyAdapter.updateMode(state.mode)
|
|
|
|
val first = layoutManager.findFirstVisibleItemPosition()
|
|
|
|
val last = layoutManager.findLastVisibleItemPosition() + 1
|
|
|
|
historyAdapter.notifyItemRangeChanged(first, last - first)
|
|
|
|
|
|
|
|
if (state.mode::class != oldMode::class) {
|
|
|
|
interactor.onModeSwitched()
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state.mode is HistoryFragmentState.Mode.Editing) {
|
|
|
|
val unselectedItems = oldMode.selectedItems - state.mode.selectedItems
|
|
|
|
|
|
|
|
state.mode.selectedItems.union(unselectedItems).forEach { item ->
|
|
|
|
historyAdapter.notifyItemChanged(item.position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
when (val mode = state.mode) {
|
|
|
|
is HistoryFragmentState.Mode.Normal -> {
|
|
|
|
setUiForNormalMode(
|
|
|
|
context.getString(R.string.library_history)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
is HistoryFragmentState.Mode.Editing -> {
|
|
|
|
setUiForSelectingMode(
|
|
|
|
context.getString(R.string.history_multi_select_title, mode.selectedItems.size)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun updateEmptyState(userHasHistory: Boolean) {
|
|
|
|
binding.historyList.isVisible = userHasHistory
|
|
|
|
binding.historyEmptyView.isVisible = !userHasHistory
|
|
|
|
with(binding.recentlyClosedNavEmpty) {
|
|
|
|
recentlyClosedNav.setOnClickListener {
|
|
|
|
interactor.onRecentlyClosedClicked()
|
|
|
|
}
|
|
|
|
val numRecentTabs = recentlyClosedNav.context.components.core.store.state.closedTabs.size
|
|
|
|
recentlyClosedTabsDescription.text = String.format(
|
|
|
|
context.getString(
|
|
|
|
if (numRecentTabs == 1) {
|
|
|
|
R.string.recently_closed_tab
|
|
|
|
} else {
|
|
|
|
R.string.recently_closed_tabs
|
|
|
|
}
|
|
|
|
),
|
|
|
|
numRecentTabs
|
|
|
|
)
|
|
|
|
recentlyClosedNav.isVisible = !userHasHistory
|
|
|
|
}
|
|
|
|
if (!userHasHistory) {
|
|
|
|
binding.historyEmptyView.announceForAccessibility(context.getString(R.string.history_empty_message))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onBackPressed(): Boolean {
|
|
|
|
return interactor.onBackPressed()
|
|
|
|
}
|
|
|
|
}
|