Skip to content

Commit

Permalink
For mozilla-mobile#356 - Gives a user the ability to delete their his…
Browse files Browse the repository at this point in the history
…tory
  • Loading branch information
boek committed Mar 29, 2019
1 parent 22fcea3 commit 2f5237c
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import android.widget.CompoundButton
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observer
import org.mozilla.fenix.R
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.history_delete.view.*
import kotlinx.android.synthetic.main.history_header.view.*
import kotlinx.android.synthetic.main.history_list_item.view.*
import mozilla.components.browser.menu.BrowserMenu
Expand Down Expand Up @@ -226,48 +224,6 @@ class HistoryAdapter(
}
}

class HistoryDeleteViewHolder(
view: View,
private val actionEmitter: Observer<HistoryAction>
) : RecyclerView.ViewHolder(view) {
private lateinit var mode: HistoryState.Mode

private val button = view.delete_history_button.apply {
setOnClickListener {
val mode = mode
if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
actionEmitter.onNext(HistoryAction.Delete.Some(mode.selectedItems))
} else {
actionEmitter.onNext(HistoryAction.Delete.All)
}
}
}

private val text = view.delete_history_button_text.apply {
val color = ContextCompat.getColor(context, R.color.photonRed60)
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_delete)
drawable?.setTint(color)
this.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
}

fun bind(mode: HistoryState.Mode) {
this.mode = mode

val text = if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
text.context.resources.getString(R.string.history_delete_some, mode.selectedItems.size)
} else {
text.context.resources.getString(R.string.history_delete_all)
}

button.contentDescription = text
this.text.text = text
}

companion object {
const val LAYOUT_ID = R.layout.history_delete
}
}

private var historyList: HistoryList = HistoryList(emptyList())
private var mode: HistoryState.Mode = HistoryState.Mode.Normal

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class HistoryComponent(

override val reducer: (HistoryState, HistoryChange) -> HistoryState = { state, change ->
when (change) {
is HistoryChange.Change -> state.copy(items = change.list)
is HistoryChange.Change -> state.copy(mode = HistoryState.Mode.Normal, items = change.list)
is HistoryChange.EnterEditMode -> state.copy(mode = HistoryState.Mode.Editing(listOf(change.item)))
is HistoryChange.AddItemForRemoval -> {
val mode = state.mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import androidx.navigation.NavOptions
import androidx.navigation.Navigation
import kotlinx.android.synthetic.main.fragment_history.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.coroutineScope
import mozilla.components.support.base.feature.BackHandler
import org.mozilla.fenix.utils.ItsNotBrokenSnack
import org.mozilla.fenix.R
Expand All @@ -29,6 +30,7 @@ import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter
import kotlin.coroutines.CoroutineContext

@SuppressWarnings("TooManyFunctions")
class HistoryFragment : Fragment(), CoroutineScope, BackHandler {

private lateinit var job: Job
Expand Down Expand Up @@ -81,18 +83,13 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

launch(Dispatchers.IO) {
val items = requireComponents.core.historyStorage.getDetailedVisits(0)
.asReversed()
.mapIndexed { id, item -> HistoryItem(id, item.url, item.visitTime) }

launch(Dispatchers.Main) {
getManagedEmitter<HistoryChange>().onNext(HistoryChange.Change(items))
}
reloadData()
}
}

// This method triggers the complexity warning. However it's actually not that hard to understand.
@SuppressWarnings("ComplexMethod")
override fun onStart() {
super.onStart()
getAutoDisposeObservable<HistoryAction>()
Expand All @@ -107,6 +104,20 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
.onNext(HistoryChange.RemoveItemForRemoval(it.item))
is HistoryAction.BackPressed -> getManagedEmitter<HistoryChange>()
.onNext(HistoryChange.ExitEditMode)
is HistoryAction.Delete.All -> launch(Dispatchers.IO) {
requireComponents.core.historyStorage.deleteEverything()
reloadData()
}
is HistoryAction.Delete.One -> launch(Dispatchers.IO) {
requireComponents.core.historyStorage.deleteVisit(it.item.url, it.item.visitedAt)
reloadData()
}
is HistoryAction.Delete.Some -> launch(Dispatchers.IO) {
it.items.forEach { item ->
requireComponents.core.historyStorage.deleteVisit(item.url, item.visitedAt)
}
reloadData()
}
}
}
}
Expand All @@ -128,4 +139,16 @@ class HistoryFragment : Fragment(), CoroutineScope, BackHandler {
}

override fun onBackPressed(): Boolean = (historyComponent.uiView as HistoryUIView).onBackPressed()

private suspend fun reloadData() {
val items = requireComponents.core.historyStorage.getDetailedVisits(0)
.asReversed()
.mapIndexed { id, item -> HistoryItem(id, item.url, item.visitTime) }

coroutineScope {
launch(Dispatchers.Main) {
getManagedEmitter<HistoryChange>().onNext(HistoryChange.Change(items))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ package org.mozilla.fenix.library.history

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.component_history.view.*
import mozilla.components.support.base.feature.BackHandler
import org.mozilla.fenix.R
import org.mozilla.fenix.mvi.UIView
Expand All @@ -26,22 +27,48 @@ class HistoryUIView(
var mode: HistoryState.Mode = HistoryState.Mode.Normal
private set

override val view: RecyclerView = LayoutInflater.from(container.context)
override val view: NestedScrollView = LayoutInflater.from(container.context)
.inflate(R.layout.component_history, container, true)
.findViewById(R.id.history_list)
.findViewById(R.id.history_wrapper)

init {
view.apply {
view.history_list.apply {
adapter = HistoryAdapter(actionEmitter)
layoutManager = LinearLayoutManager(container.context)
}

view.delete_history_button.setOnClickListener {
val mode = mode
val action = when (mode) {
is HistoryState.Mode.Normal -> HistoryAction.Delete.All
is HistoryState.Mode.Editing -> HistoryAction.Delete.Some(mode.selectedItems)
}

actionEmitter.onNext(action)
}
}

override fun updateView() = Consumer<HistoryState> {
mode = it.mode
(view.adapter as HistoryAdapter).updateData(it.items, it.mode)
updateDeleteButton()
(view.history_list.adapter as HistoryAdapter).updateData(it.items, it.mode)
}

private fun updateDeleteButton() {
val mode = mode

val text = if (mode is HistoryState.Mode.Editing && mode.selectedItems.isNotEmpty()) {
view.delete_history_button_text.context.resources.getString(
R.string.history_delete_some,
mode.selectedItems.size
)
} else {
view.delete_history_button_text.context.resources.getString(R.string.history_delete_all)
}

view.delete_history_button.contentDescription = text
view.delete_history_button_text.text = text
}
override fun onBackPressed(): Boolean {
if (mode is HistoryState.Mode.Editing) {
actionEmitter.onNext(HistoryAction.BackPressed)
Expand Down
42 changes: 38 additions & 4 deletions app/src/main/res/layout/component_history.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,42 @@
- 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/. -->

<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/history_list"
<androidx.core.widget.NestedScrollView
android:id="@+id/history_wrapper"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_history_button"
android:foreground="?android:attr/selectableItemBackground"
android:background="@drawable/button_background"
android:layout_margin="16dp"
android:padding="6dp"
android:clickable="true"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/delete_history_button_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/history_delete_all"
android:textColor="@color/photonRed60"
android:drawablePadding="8dp"
android:textSize="16sp"
android:gravity="center"
android:clickable="false"
android:focusable="false"
android:layout_gravity="center" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/history_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
28 changes: 0 additions & 28 deletions app/src/main/res/layout/history_delete.xml

This file was deleted.

0 comments on commit 2f5237c

Please sign in to comment.