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 3c9fa5426..deb7c9ede 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -71,11 +71,13 @@ class HomeFragment : Fragment() { tabsComponent.view.isNestedScrollingEnabled = false sessionsComponent.view.isNestedScrollingEnabled = false - val bundles = requireComponents.core.sessionStorage.bundles(40) + val bundles = requireComponents.core.sessionStorage.bundles(temporaryNumberOfSessions) - bundles.observe(this, Observer {sessionBundles -> + bundles.observe(this, Observer { sessionBundles -> val archivedSessions = sessionBundles.mapNotNull { sessionBundle -> - sessionBundle.id?.let { ArchivedSession(it, sessionBundle, sessionBundle.lastSavedAt, sessionBundle.urls) } + sessionBundle.id?.let { + ArchivedSession(it, sessionBundle, sessionBundle.lastSavedAt, sessionBundle.urls) + } } getManagedEmitter().onNext(SessionsChange.Changed(archivedSessions)) @@ -171,6 +173,9 @@ class HomeFragment : Fragment() { requireComponents.core.sessionManager.restore(this) } } + is SessionsAction.Delete -> { + requireComponents.core.sessionStorage.remove(it.archivedSession.bundle) + } } } } @@ -246,5 +251,7 @@ class HomeFragment : Fragment() { const val toolbarPaddingDp = 12f const val firstKeyTriggerFrame = 55 const val secondKeyTriggerFrame = 90 + + const val temporaryNumberOfSessions = 25 } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessions/SessionItemMenu.kt b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionItemMenu.kt new file mode 100644 index 000000000..54704ef45 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionItemMenu.kt @@ -0,0 +1,31 @@ +/* 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.sessions + +import android.content.Context +import mozilla.components.browser.menu.BrowserMenuBuilder +import mozilla.components.browser.menu.item.SimpleBrowserMenuItem +import org.mozilla.fenix.R + +class SessionItemMenu( + private val context: Context, + private val onItemTapped: (Item) -> Unit = {} +) { + sealed class Item { + object Delete : Item() + } + + val menuBuilder by lazy { BrowserMenuBuilder(menuItems) } + + private val menuItems by lazy { + listOf( + SimpleBrowserMenuItem( + context.getString(R.string.session_item_delete) + ) { + onItemTapped.invoke(Item.Delete) + } + ) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsAdapter.kt index 6c0b329a2..238c0c334 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsAdapter.kt @@ -19,7 +19,9 @@ import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.session_item.* import org.mozilla.fenix.R -class SessionsAdapter(private val actionEmitter: Observer) : RecyclerView.Adapter() { +class SessionsAdapter( + private val actionEmitter: Observer +) : RecyclerView.Adapter() { private var items = listOf() fun reloadDatat(items: List) { @@ -89,20 +91,27 @@ class SessionsAdapter(private val actionEmitter: Observer) : Rec view: View, private val actionEmitter: Observer, override val containerView: View? = view - ) :RecyclerView.ViewHolder(view), LayoutContainer { + ) : RecyclerView.ViewHolder(view), LayoutContainer { private var session: ArchivedSession? = null + private lateinit var sessionMenu: SessionItemMenu init { + setupMenu() + session_item.setOnClickListener { session?.apply { actionEmitter.onNext(SessionsAction.Select(this)) } } + + session_card_overflow_button.setOnClickListener { + sessionMenu.menuBuilder.build(itemView.context).show(it) + } } fun bind(session: ArchivedSession) { this.session = session session_card_thumbnail.setColorFilter( - ContextCompat.getColor(itemView.context, AVAILABLE_COLOR_IDS.random()), + ContextCompat.getColor(itemView.context, availableColors.random()), PorterDuff.Mode.MULTIPLY) session_card_timestamp.text = session.formattedSavedAt session_card_titles.text = session.titles @@ -111,8 +120,18 @@ class SessionsAdapter(private val actionEmitter: Observer) : Rec } else { "" } } + private fun setupMenu() { + sessionMenu = SessionItemMenu(itemView.context) { + if (it is SessionItemMenu.Item.Delete) { + session?.apply { + actionEmitter.onNext(SessionsAction.Delete(this)) + } + } + } + } + companion object { - private val AVAILABLE_COLOR_IDS = listOf( + private val availableColors = listOf( R.color.photonBlue40, R.color.photonGreen50, R.color.photonYellow50, R.color.photonOrange50, R.color.photonPurple50, R.color.photonInk70) const val LAYOUT_ID = R.layout.session_item diff --git a/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsComponent.kt b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsComponent.kt index fd901f919..caa9da614 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessions/SessionsComponent.kt @@ -14,19 +14,21 @@ import org.mozilla.fenix.mvi.UIComponent import org.mozilla.fenix.mvi.ViewState import java.net.URL import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Calendar +import java.util.Locale data class ArchivedSession( val id: Long, val bundle: SessionBundle, private val savedAt: Long, - private val _urls: List) { + private val _urls: List +) { val formattedSavedAt by lazy { val isSameDay: (Calendar, Calendar) -> Boolean = { a, b -> a.get(Calendar.ERA) == b.get(Calendar.ERA) && a.get(Calendar.YEAR) == b.get(Calendar.YEAR) && a.get(Calendar.DAY_OF_YEAR) == b.get(Calendar.DAY_OF_YEAR) - } val parse: (Date) -> String = { date -> @@ -34,11 +36,10 @@ data class ArchivedSession( val today = Calendar.getInstance() val yesterday = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -1) } - val time = TIME_FORMATTER.format(date) - val month = MONTH_FORMATTER.format(date) - val day = DAY_FORMATTER.format(date) - val dayOfWeek = DAY_OF_WEEK_FORMATTER.format(date) - + val time = timeFormatter.format(date) + val month = monthFormatter.format(date) + val day = dayFormatter.format(date) + val dayOfWeek = dayOfWeekFormatter.format(date) when { isSameDay(dateCal, today) -> "Today @ $time" @@ -51,6 +52,9 @@ data class ArchivedSession( } val titles by lazy { + // Until we resolve (https://github.com/mozilla-mobile/fenix/issues/532) we + // just want to grab the host from the URL + @SuppressWarnings("TooGenericExceptionCaught") val urlFormatter: (String) -> String = { url -> try { URL(url).host @@ -69,10 +73,10 @@ data class ArchivedSession( private companion object { private const val NUMBER_OF_URLS_TO_DISPLAY = 5 - private val TIME_FORMATTER = SimpleDateFormat("h:mm a", Locale.US) - private val MONTH_FORMATTER = SimpleDateFormat("M", Locale.US) - private val DAY_FORMATTER = SimpleDateFormat("d", Locale.US) - private val DAY_OF_WEEK_FORMATTER = SimpleDateFormat("EEEE", Locale.US) + private val timeFormatter = SimpleDateFormat("h:mm a", Locale.US) + private val monthFormatter = SimpleDateFormat("M", Locale.US) + private val dayFormatter = SimpleDateFormat("d", Locale.US) + private val dayOfWeekFormatter = SimpleDateFormat("EEEE", Locale.US) } } @@ -88,7 +92,7 @@ class SessionsComponent( override val reducer: (SessionsState, SessionsChange) -> SessionsState = { state, change -> when (change) { - is SessionsChange.Changed -> state.copy(archivedSessions = change.archivedSessions) // copy state with changes here + is SessionsChange.Changed -> state.copy(archivedSessions = change.archivedSessions) } } @@ -105,6 +109,7 @@ data class SessionsState(val archivedSessions: List) : ViewStat sealed class SessionsAction : Action { data class Select(val archivedSession: ArchivedSession) : SessionsAction() + data class Delete(val archivedSession: ArchivedSession) : SessionsAction() } sealed class SessionsChange : Change { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4569a2c14..e9335b912 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -163,6 +163,14 @@ people before profit. Our mission: keep the Internet open and accessible to all. Current session image + + Delete + + + %1$d sites… + + Delete History